{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### torch 基本处理单元"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\n",
       "1.00000e-03 *\n",
       " -6.7953  0.0000 -6.7953  0.0000\n",
       "  0.0000  0.0000  0.0000  0.0000\n",
       "  0.0000  0.0000  0.0000  0.0000\n",
       "  0.0000  0.0000  0.0000  0.0000\n",
       "  0.0000  0.0000  0.0000  0.0000\n",
       "[torch.FloatTensor of size 5x4]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回的数组大小5x4的矩阵\n",
    "torch.Tensor(5, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\n",
       " 0.7977  0.1654  0.8409  0.7564\n",
       " 0.3139  0.2253  0.6559  0.2096\n",
       " 0.3448  0.7688  0.8343  0.9917\n",
       " 0.2122  0.1920  0.1087  0.3080\n",
       " 0.9847  0.0374  0.2029  0.7608\n",
       "[torch.FloatTensor of size 5x4]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回的数组大小是5x4的矩阵，初始化是0~1的均匀分布\n",
    "torch.rand(5, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([5, 4])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 得到矩阵大小\n",
    "a = torch.rand(5, 4)\n",
    "a.size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.,  1.,  1.,  1.],\n",
       "       [ 1.,  1.,  1.,  1.],\n",
       "       [ 1.,  1.,  1.,  1.],\n",
       "       [ 1.,  1.,  1.,  1.],\n",
       "       [ 1.,  1.,  1.,  1.]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# numpy 类似的返回5x4大小的矩阵\n",
    "np.ones((5, 4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[  7.89588690e-01   7.43446290e-01   1.61940977e-01   4.80842412e-01]\n",
      " [  1.78743862e-02   1.91753581e-01   3.34077984e-01   3.44260454e-01]\n",
      " [  3.15251201e-01   1.37171671e-01   3.29199225e-01   1.57159448e-01]\n",
      " [  7.46150970e-01   8.45601916e-01   9.45035994e-01   4.01963502e-01]\n",
      " [  4.72619027e-01   1.90935910e-01   8.99520470e-04   3.92095864e-01]]\n"
     ]
    }
   ],
   "source": [
    "# numpy 和 torch.Tensor 之间的转换\n",
    "a = torch.rand(5, 4)\n",
    "b = a.numpy()\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 3  4\n",
      " 3  6\n",
      "[torch.LongTensor of size 2x2]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[3, 4], [3, 6]])\n",
    "b = torch.from_numpy(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运算和numpy类似"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "x = torch.rand(5, 4)\n",
    "y = torch.rand(5, 4)\n",
    "c = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 1.8998  2.4494  0.4745  2.7200\n",
      " 2.7077  2.6774  2.5322  1.7018\n",
      " 2.1523  1.3062  2.9104  0.8672\n",
      " 2.3793  1.4136  2.4238  0.4781\n",
      " 0.3026  0.1418  0.9806  2.1584\n",
      "[torch.FloatTensor of size 5x4]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(c * x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 1.4478  1.1207  0.7065  1.4593\n",
      " 1.5152  1.4361  1.8031  0.5893\n",
      " 0.9860  0.4821  1.2809  0.5736\n",
      " 1.6838  1.1084  0.9404  0.7543\n",
      " 0.1237  0.1471  0.8376  1.2901\n",
      "[torch.FloatTensor of size 5x4]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(x + y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 1.4478  1.1207  0.7065  1.4593\n",
      " 1.5152  1.4361  1.8031  0.5893\n",
      " 0.9860  0.4821  1.2809  0.5736\n",
      " 1.6838  1.1084  0.9404  0.7543\n",
      " 0.1237  0.1471  0.8376  1.2901\n",
      "[torch.FloatTensor of size 5x4]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(x.add(y))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\n",
       " 1.4478  1.1207  0.7065  1.4593\n",
       " 1.5152  1.4361  1.8031  0.5893\n",
       " 0.9860  0.4821  1.2809  0.5736\n",
       " 1.6838  1.1084  0.9404  0.7543\n",
       " 0.1237  0.1471  0.8376  1.2901\n",
       "[torch.FloatTensor of size 5x4]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 可以直接进行操作改变原对象，x+y或者x.add()并不会改变x，但是x.add_()则会对x进行改变\n",
    "x.add_(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 1.4478  1.1207  0.7065  1.4593\n",
      " 1.5152  1.4361  1.8031  0.5893\n",
      " 0.9860  0.4821  1.2809  0.5736\n",
      " 1.6838  1.1084  0.9404  0.7543\n",
      " 0.1237  0.1471  0.8376  1.2901\n",
      "[torch.FloatTensor of size 5x4]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将 torch.Tensor 放到 GPU 上"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 判断一下电脑是否支持GPU\n",
    "torch.cuda.is_available()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " 0.6592  0.4923  0.6790  0.8395\n",
      " 0.5175  0.1796  0.4245  0.1928\n",
      " 0.1701  0.1957  0.3858  0.8376\n",
      " 0.4047  0.1358  0.2725  0.5413\n",
      " 0.7260  0.6121  0.6860  0.9933\n",
      "[torch.cuda.FloatTensor of size 5x4 (GPU 0)]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "a = torch.rand(5, 4)\n",
    "a = a.cuda()\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### torch 的自动求导功能\n",
    "torch 和大部分框架一样有着自动求导功能，对象不再是 torch.Tensor，而是torch.autograd.Variable\n",
    "\n",
    "本质上Variable和Tensor没有什么区别，不过Variable会放在一个计算图里面，可以进行前向传播和反向传播以及求导  \n",
    "\n",
    "![1.png](http://upload-images.jianshu.io/upload_images/3623720-1c2694b72e0341ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n",
    "\n",
    "里面的creator表示通过什么操作得到的这个Variable，grad表示反向传播的梯度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from torch.autograd import Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "# requires_grad 表示是否对其求梯度，默认是False\n",
    "x = Variable(torch.Tensor([3]), requires_grad=True)\n",
    "y = Variable(torch.Tensor([5]), requires_grad=True)\n",
    "z = 2 * x + y + 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对 x 和 y 分别求导\n",
    "z.backward()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dz/dx: \n",
      " 2\n",
      "[torch.FloatTensor of size 1]\n",
      "\n",
      "dz/dy: \n",
      " 1\n",
      "[torch.FloatTensor of size 1]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# x 的导数和 y 的导数\n",
    "print('dz/dx: {}'.format(x.grad.data))\n",
    "print('dz/dy: {}'.format(y.grad.data))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 神经网络部分\n",
    "\n",
    "所依赖的主要是 torch.nn 和 torch.nn.functional\n",
    "\n",
    "torch.nn 里面有着所有的神经网络的层的操作，其用来构建网络，只有执行一次网络的运算才执行一次\n",
    "\n",
    "torch.nn.functional 表示的是直接对其做一次向前运算操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "import torch.nn.functional as F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 基本的网络构建类模板\n",
    "class net_name(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(net_name, self).__init__()\n",
    "        # 可以添加各种网络层\n",
    "        self.conv1 = nn.Conv2d(3, 10, 3)\n",
    "        # 具体每种层的参数可以去查看文档\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # 定义向前传播\n",
    "        out = self.conv1(x)\n",
    "        return out"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
